/*
 *	jsondata.h
 *
 *	Copyright (C) 2024-2024  Arthur Wang
 *	wang.wudong@qq.com
 *	This file is part of JSONDATA https://

	json parses and establishes a json data structure in a string.
	You can check the value by name, and you can also gradually build a json data structure.
	The json data structure can be output to the specified buffer through the serialization function.

 	example:
	jsondata* parms = new jsondata();
	jsondata* datas = new jsondata();

	parms->addvalue("pd",1);
	parms->addvalue("pd2","da");
	parms->addvalue("pd3",1);
	parms->addvalue("pdatas",datas);

	datas->addvalue("d",1);
	datas->addvalue("d2","da");
	datas->addvalue("d3",1);

	char buffer[512];

	parms->serializeJson(buffer,sizeof(buffer));
	printf(buffer);

	example:
	printf(parms->getstr("pd3")));



	example:
	jsondata* h = new jsondata();

	h->deserializeJson(buffer,sizeof(buffer));
	h->serializeJson(buffer,sizeof(buffer));
	printf(buffer);
 */

#ifndef JSONDATA_H
#define JSONDATA_H

#include <iostream>

class jsondata {
	private:
		class dataType {
			public:
				char name[50];
				char str[50];
				int value;
			public:
				dataType(char* name) {
					strcpy(this->name,name);
					this->value = 0;
					this->str[0] = 0;
				}
				dataType(char* name,int value) {
					strcpy(this->name,name);
					this->value = value;
					snprintf(this->str,50,"%d",value);
				}
				dataType(char* name,char* str) {
					strcpy(this->name,name);
					this->value = 0;
					strcpy(this->str,str);
				}
				int scmp(char* name) {
					return strcmp(name,this->name);
				}

		};
		dataType* pdata;

		int findname(char* name,jsondata **out) {
			if ((pdata != NULL) && (!pdata->scmp(name))) {
				*out = this;
				return 1;
			}
			if ((child != NULL) && (child->findname(name,out))) {
				return 1;
			}
			if ((next != NULL) && (next->findname(name,out))) {
				return 1;
			}

			return 0;
		}
	public:
		jsondata* next;
		jsondata* child;

		jsondata() {
			this->pdata = NULL;
			this->next = NULL;
			this->child = NULL;
		}

		jsondata(char* name,int value) {
			this->pdata = new dataType(name,value);
			this->next = NULL;
			this->child = NULL;
		}

		jsondata(char* name,char* str) {
			this->pdata = new dataType(name,str);
			this->next = NULL;
			this->child = NULL;
		}
		jsondata(char* name,jsondata* child) {
			if (strlen(name)>0) {
				this->pdata = new dataType(name);
			} else {
				this->pdata = NULL;
			}

			this->next = NULL;
			this->child = child;
		}

		int strout(char *out,int* plen,int* pll) {
			char t = 0;
			if (*pll <= 0) {
				return 0;
			}

			if (pdata != NULL)  {
				t = snprintf(out+*plen,*pll,"%s:%s",pdata->name,pdata->str);
				*plen += t;
				*pll -= t;
			}

			if (child != NULL) {
				t = snprintf(out+*plen,*pll,"{");
				*plen += t;
				*pll -= t;

				child->strout(out,plen,pll);
				t = snprintf(out+*plen,*pll,"}");
				*plen += t;
				*pll -= t;
			}

			if (next != NULL) {
				if (pdata != NULL) {
					t = snprintf(out+*plen,*pll,",");
					*plen += t;
					*pll -= t;
				}
				next->strout(out,plen,pll);
			}
			return 1;
		}

		addvalue(char* substr) {
			char* ptr = strchr(substr,':');
			char name[50];
			char str[50];

			if (ptr == NULL) {
				return false;
			}
			ptr[0]=0;

			if (strlen(str) == 0) {
				addvalue(substr,new jsondata());
			} else {
				addvalue(substr,ptr+1);
			}

			return true;
		}

		addvalue(char* name,int value) {
			if (next == NULL) {
				next = new jsondata(name,value);
			} else {
				next->addvalue(name,value);
			}
		}
		addvalue(char* name,char* str) {
			if (next == NULL) {
				next = new jsondata(name,str);
			} else {
				next->addvalue(name,str);
			}
		}
		addvalue(char* name,jsondata* child) {
			if (next == NULL) {
				next = new jsondata(name,child);
			} else {
				next->addvalue(name,child);
			}
		}
		serializeJson(char *out,int ll) {
			out[0]= 0;
			int len =0;
			strout(out,&len,&ll);
		}
		int strin(char *in,int* plen,int* pll,char* name,char* str) {
			jsondata* parms = NULL;

			char d = in[*plen];
			name[0]=0;
			str[0]=0;

			while(d) {
				(*plen)++;

				switch(d) {

					case '\{':
						*pll = *plen;
						parms = new jsondata();
						addvalue(name,parms);
						parms->strin(in,plen,pll,name,str);
						break;
					case '}':
						if (*plen-*pll-1>0) {
							strncpy(str,in+*pll,*plen-*pll-1);
							str[*plen-*pll-1]=0;
							*pll = *plen;
							addvalue(name,str);
						}
						return true;
						break;
					case ',':
						strncpy(str,in+*pll,*plen-*pll-1);
						str[*plen-*pll-1]=0;
						*pll = *plen;
						addvalue(name,str);

						break;
					case ':':
						strncpy(name,in+*pll,*plen-*pll-1);
						name[*plen-*pll-1]=0;
						*pll = *plen;
						break;
				}

				d = in[*plen];
			}
		}

		deserializeJson(char *in) {
			int len = 0;
			int ll = 0;
			char name[50];
			char str[50];

			strin(in,&len,&ll,name,str);
		}
		char* getstr(char* name) {
			jsondata* out;

			if(findname(name,&out)) {
				return out->pdata->str;
			} else {
				return NULL;
			}
		}
};


#endif